<script setup lang="ts">
import type { Recordable } from '@vben/types';

import { ref, unref } from 'vue';

import {
  Button,
  RadioButton,
  RadioGroup,
  Spin,
  TabPane,
  Tabs,
} from 'ant-design-vue';
import consola from 'consola';
import hljs from 'highlight.js/lib/core';
import java from 'highlight.js/lib/languages/java';
import javascript from 'highlight.js/lib/languages/javascript';
import sql from 'highlight.js/lib/languages/sql';
import typescript from 'highlight.js/lib/languages/typescript';
import xml from 'highlight.js/lib/languages/xml';

import { DefGenTableApi } from '#/api/devOperation/developer/defGenTable';
import { TemplateEnum } from '#/enums/system';
import { useCopyToClipboard } from '#/hooks/web/useCopyToClipboard';
import { useMessage } from '#/hooks/web/useMessage';

import 'highlight.js/styles/github-dark-dimmed.css';

hljs.registerLanguage('java', java);
hljs.registerLanguage('xml', xml);
hljs.registerLanguage('html', xml);
hljs.registerLanguage('vue', xml);
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('sql', sql);
hljs.registerLanguage('web', xml);
hljs.registerLanguage('ts', typescript);

const { createMessage } = useMessage();
const tableMap = ref<
  Record<string, Record<TemplateEnum, Record<string, string>>>
>({});
const tableNameMap = ref<Recordable>({});
const spinning = ref<boolean>(false);
const currentTabRef = ref<string>('');
const currentCodeRef = ref<string>('');
const template = ref<TemplateEnum>(TemplateEnum.BACKEND);
const { clipboardRef, copiedRef } = useCopyToClipboard();

const reload = async (tableId: string, temp?: TemplateEnum) => {
  try {
    spinning.value = true;
    const varTemp = temp || template.value;
    const tableCode = tableMap.value[tableId] as Record<
      TemplateEnum,
      Record<string, string>
    >;

    tableCode[varTemp] = {};
    const map = await DefGenTableApi.previewCode(tableId, varTemp);
    tableCode[varTemp] = map;

    currentTabRef.value = tableId;
    // eslint-disable-next-line no-unreachable-loop
    for (const key in tableCode[template.value]) {
      currentCodeRef.value = key;
      break;
    }
  } finally {
    spinning.value = false;
  }
};
const load = async (tableId: string) => {
  const tableIdList = tableId.includes(',') ? tableId.split(',') : [tableId];

  for (const id of tableIdList) {
    tableMap.value[id] = {} as Record<TemplateEnum, Record<string, string>>;
  }

  const list = await DefGenTableApi.findTableList(tableIdList);

  for (const item of list) {
    tableNameMap.value[item.id as string] = item.name;
  }

  await reload(tableIdList[0] as string);
};

async function updateTabs(tableId: string) {
  currentTabRef.value = tableId;
  const temp = template.value;
  if (!tableMap.value[tableId]?.[temp]) {
    await reload(tableId, temp as TemplateEnum);
  }
}
async function updateTemplate(tableId: string, temp: TemplateEnum) {
  if (tableMap.value[tableId]?.[temp]) {
    currentTabRef.value = tableId;
    // eslint-disable-next-line no-unreachable-loop
    for (const key in tableMap.value[tableId][template.value]) {
      currentCodeRef.value = key;
      break;
    }
    consola.log(currentCodeRef.value);
  } else {
    await reload(tableId, temp);
  }
}

function getTabName(key: string) {
  return tableNameMap.value[key];
}

function handleCopy(value: string) {
  if (!value) {
    createMessage.warning('当前页面无内容，无需复制。');
    return;
  }
  clipboardRef.value = value;
  if (unref(copiedRef)) {
    createMessage.success('复制成功！');
  }
}

function getKey(key: string) {
  const k = key.slice(key.lastIndexOf('/') + 1, key.indexOf('.ftl'));
  if (key.startsWith('sub-')) {
    return `${k}(从表)`;
  }
  return k;
}

function highlightedCode(code: string, key: string) {
  const ftlName = key.slice(key.lastIndexOf('/') + 1, key.indexOf('.ftl'));
  const language = ftlName.slice(ftlName.indexOf('.') + 1);
  const result = hljs.highlight(code || '', { language, ignoreIllegals: true });
  return result.value || '&nbsp;';
}
defineExpose({ load });
</script>

<template>
  <Tabs :value="currentTabRef" type="line" @update:value="updateTabs">
    <TabPane
      v-for="(tableVal, tableKey) in tableMap"
      :key="tableKey"
      :name="tableKey"
      :tab="getTabName(tableKey)"
    >
      <RadioGroup
        v-model:value="template"
        style="margin-right: 2rem"
        @update:value="updateTemplate(tableKey, $event)"
      >
        <RadioButton :value="TemplateEnum.BACKEND">后端</RadioButton>
        <RadioButton :value="TemplateEnum.WEB_PLUS">前端(Vben)</RadioButton>
        <RadioButton :value="TemplateEnum.WEB_SOYBEAN">
          前端(Soybean)
        </RadioButton>
        <RadioButton :value="TemplateEnum.WEB_VBEN5">前端(Vben5)</RadioButton>
      </RadioGroup>
      <Button type="primary" @click="reload(tableKey)">
        <!-- <template #icon><SvgIcon icon="ant-design:reload-outlined" /></template> -->
        刷新
      </Button>

      <Spin :spinning="spinning" size="large" class="mt-3">
        <Tabs
          v-model:value="currentCodeRef"
          placement="left"
          style="min-height: 400px"
          type="line"
        >
          <TabPane
            v-for="(value, key) in tableVal[template]"
            :key="key"
            :name="key"
            :tab="getKey(key)"
          >
            <pre>
              <Button pre-icon="ant-design:copy-outlined" style="float: left" @click="handleCopy(value)">复制</Button>
              <code class="hljs" v-html="highlightedCode(value, key)"></code>
            </pre>
          </TabPane>
        </Tabs>
      </Spin>
    </TabPane>
  </Tabs>
</template>

<style lang="scss" scoped>
pre {
  display: block;
  padding: 9.5px;
  margin: 0 0 10px;
  font-size: 13px;
  line-height: 1.4;
  color: #333;
  word-break: break-all;
  word-wrap: break-word;
  background-color: #f5f5f5;
  border: 1px solid #ccc;
}
</style>
